diff options
| author | Fuwn <[email protected]> | 2024-10-09 00:41:20 -0700 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2024-10-09 00:41:43 -0700 |
| commit | 998b63a35256ac985a5a2714dd1ca451af4dfd8a (patch) | |
| tree | 50796121a9d5ab0330fdc5d7e098bda2860d9726 /src/routes/user/[user]/+page.svelte | |
| parent | feat(graphql): add badgeCount field (diff) | |
| download | due.moe-998b63a35256ac985a5a2714dd1ca451af4dfd8a.tar.xz due.moe-998b63a35256ac985a5a2714dd1ca451af4dfd8a.zip | |
chore(prettier): use spaces instead of tabs
Diffstat (limited to 'src/routes/user/[user]/+page.svelte')
| -rw-r--r-- | src/routes/user/[user]/+page.svelte | 1076 |
1 files changed, 538 insertions, 538 deletions
diff --git a/src/routes/user/[user]/+page.svelte b/src/routes/user/[user]/+page.svelte index 84f121ea..d60ea8e5 100644 --- a/src/routes/user/[user]/+page.svelte +++ b/src/routes/user/[user]/+page.svelte @@ -1,550 +1,550 @@ <script lang="ts"> - import settings from '$stores/settings'; - import ParallaxImage from '../../../lib/Image/ParallaxImage.svelte'; - import { typeSchedule, type ParseResult } from '$lib/Hololive/hololive'; - import HeadTitle from '$lib/Home/HeadTitle.svelte'; - import Message from '$lib/Loading/Message.svelte'; - import { estimatedDayReading } from '$lib/Media/Manga/time'; - import Skeleton from '$lib/Loading/Skeleton.svelte'; - import root from '$lib/Utility/root'; - import locale from '$stores/locale'; - import { onMount } from 'svelte'; - import authorisedUsers from '$lib/Data/Static/authorised.json'; - import tooltip from '$lib/Tooltip/tooltip'; - import AnimeRateLimited from '$lib/Error/AnimeRateLimited.svelte'; - import identity from '$stores/identity'; - import SettingHint from '$lib/Settings/SettingHint.svelte'; - import proxy from '$lib/Utility/proxy'; - import { parseScheduleHtml } from '$lib/Data/hololive'; - import type { Preferences } from '../../../graphql/$types'; - import SvelteMarkdown from 'svelte-markdown'; - import MarkdownLink from '$lib/MarkdownLink.svelte'; - import LinkedTooltip from '$lib/Tooltip/LinkedTooltip.svelte'; - import { graphql } from '$houdini'; - - export let data; - - $: ({ Profile } = data); - $: preferences = $Profile.fetching ? undefined : ($Profile.data?.User.preferences as Preferences); - - const setCategoriesQuery = graphql(` - mutation SetCategories($categories: [String!]!) { - setPinnedBadgeWallCategories(categories: $categories) { - id - - preferences { - pinned_badge_wall_categories - } - } - } - `); - - const toggleCategoryQuery = graphql(` - mutation ToggleCategory($category: String!) { - togglePinnedBadgeWallCategory(category: $category) { - id - - preferences { - pinned_badge_wall_categories - } - } - } - `); - - const toggleHideMissingBadgesQuery = graphql(` - mutation ToggleHideMissingBadges { - toggleHideMissingBadges { - id - - preferences { - hide_missing_badges - } - } - } - `); - - const toggleHideAWCBadgesQuery = graphql(` - mutation ToggleHideAWCBadges { - toggleHideAWCBadges { - id - - preferences { - hide_awc_badges - } - } - } - `); - - const setBiographyQuery = graphql(` - mutation SetBiography($biography: String!) { - setBiography(biography: $biography) { - id - - preferences { - biography - } - } - } - `); - - const setBadgeWallCSSQuery = graphql(` - mutation SetBadgeWallCSS($css: String!) { - setBadgeWallCSS(css: $css) { - id - - preferences { - badge_wall_css - } - } - } - `); - - $: userData = data.userData; - - let error = false; - let schedule: ParseResult | undefined = undefined; - let draggedCategory: string | null = null; - let draggedOverCategory: string | null = null; - - $: displayBadges = (username: string, badges: number | string) => - $locale({ - values: { - badges: badges, - username - } - }).user.profile.badges; - - const handleDragStart = ( - event: DragEvent & { currentTarget: EventTarget & HTMLDivElement }, - category: string | null - ) => { - draggedCategory = category; - - if (event.dataTransfer) event.dataTransfer.effectAllowed = 'move'; - }; - - const handleDragOver = (event: any) => { - event.preventDefault(); - - event.dataTransfer.dropEffect = 'move'; - }; - - const handleDragEnter = ( - event: DragEvent & { currentTarget: EventTarget & HTMLDivElement }, - category: string | null - ) => { - event.preventDefault(); - - if (draggedCategory !== category && preferences && draggedCategory) { - draggedOverCategory = category; - - const categories = preferences.pinned_badge_wall_categories; - const draggedIndex = categories.indexOf(draggedCategory); - const targetIndex = categories.indexOf(category || ''); - - categories.splice(draggedIndex, 1); - categories.splice(targetIndex, 0, draggedCategory); - - preferences.pinned_badge_wall_categories = categories; - } - }; - - const handleDragLeave = ( - event: DragEvent & { currentTarget: EventTarget & HTMLDivElement }, - category: string - ) => { - event.preventDefault(); - - if (draggedOverCategory === category && preferences && draggedCategory) { - draggedOverCategory = null; - - const categories = preferences.pinned_badge_wall_categories; - const draggedIndex = categories.indexOf(draggedCategory); - - categories.splice(draggedIndex, 1); - categories.splice(categories.indexOf(category) + 1, 0, draggedCategory); - - preferences.pinned_badge_wall_categories = categories; - } - }; - - const handleDrop = (event: { preventDefault: () => void }) => { - event.preventDefault(); - - if (userData && preferences) - setCategoriesQuery - .mutate({ - categories: preferences.pinned_badge_wall_categories - }) - .then(); - - draggedCategory = null; - draggedOverCategory = null; - }; - - onMount(async () => { - schedule = typeSchedule( - parseScheduleHtml( - await ( - await fetch(proxy('https://schedule.hololive.tv'), { - headers: { - Cookie: 'timezone=Asia/Tokyo' - } - }) - ).text() - ) - ); - }); - - const getBadgeWallCSS = () => - (document.getElementById('badgeWallCSS') as HTMLTextAreaElement).value; - - const getBiography = () => - (document.getElementById('biography') as HTMLTextAreaElement).value.slice(0, 3000); - - const toggleCategory = () => { - if (!userData) return; - - const categoryElement = document.getElementById('category') as HTMLInputElement; - const category = categoryElement.value; - - toggleCategoryQuery.mutate({ category }).then(); - - categoryElement.value = ''; - }; + import settings from '$stores/settings'; + import ParallaxImage from '../../../lib/Image/ParallaxImage.svelte'; + import { typeSchedule, type ParseResult } from '$lib/Hololive/hololive'; + import HeadTitle from '$lib/Home/HeadTitle.svelte'; + import Message from '$lib/Loading/Message.svelte'; + import { estimatedDayReading } from '$lib/Media/Manga/time'; + import Skeleton from '$lib/Loading/Skeleton.svelte'; + import root from '$lib/Utility/root'; + import locale from '$stores/locale'; + import { onMount } from 'svelte'; + import authorisedUsers from '$lib/Data/Static/authorised.json'; + import tooltip from '$lib/Tooltip/tooltip'; + import AnimeRateLimited from '$lib/Error/AnimeRateLimited.svelte'; + import identity from '$stores/identity'; + import SettingHint from '$lib/Settings/SettingHint.svelte'; + import proxy from '$lib/Utility/proxy'; + import { parseScheduleHtml } from '$lib/Data/hololive'; + import type { Preferences } from '../../../graphql/$types'; + import SvelteMarkdown from 'svelte-markdown'; + import MarkdownLink from '$lib/MarkdownLink.svelte'; + import LinkedTooltip from '$lib/Tooltip/LinkedTooltip.svelte'; + import { graphql } from '$houdini'; + + export let data; + + $: ({ Profile } = data); + $: preferences = $Profile.fetching ? undefined : ($Profile.data?.User.preferences as Preferences); + + const setCategoriesQuery = graphql(` + mutation SetCategories($categories: [String!]!) { + setPinnedBadgeWallCategories(categories: $categories) { + id + + preferences { + pinned_badge_wall_categories + } + } + } + `); + + const toggleCategoryQuery = graphql(` + mutation ToggleCategory($category: String!) { + togglePinnedBadgeWallCategory(category: $category) { + id + + preferences { + pinned_badge_wall_categories + } + } + } + `); + + const toggleHideMissingBadgesQuery = graphql(` + mutation ToggleHideMissingBadges { + toggleHideMissingBadges { + id + + preferences { + hide_missing_badges + } + } + } + `); + + const toggleHideAWCBadgesQuery = graphql(` + mutation ToggleHideAWCBadges { + toggleHideAWCBadges { + id + + preferences { + hide_awc_badges + } + } + } + `); + + const setBiographyQuery = graphql(` + mutation SetBiography($biography: String!) { + setBiography(biography: $biography) { + id + + preferences { + biography + } + } + } + `); + + const setBadgeWallCSSQuery = graphql(` + mutation SetBadgeWallCSS($css: String!) { + setBadgeWallCSS(css: $css) { + id + + preferences { + badge_wall_css + } + } + } + `); + + $: userData = data.userData; + + let error = false; + let schedule: ParseResult | undefined = undefined; + let draggedCategory: string | null = null; + let draggedOverCategory: string | null = null; + + $: displayBadges = (username: string, badges: number | string) => + $locale({ + values: { + badges: badges, + username + } + }).user.profile.badges; + + const handleDragStart = ( + event: DragEvent & { currentTarget: EventTarget & HTMLDivElement }, + category: string | null + ) => { + draggedCategory = category; + + if (event.dataTransfer) event.dataTransfer.effectAllowed = 'move'; + }; + + const handleDragOver = (event: any) => { + event.preventDefault(); + + event.dataTransfer.dropEffect = 'move'; + }; + + const handleDragEnter = ( + event: DragEvent & { currentTarget: EventTarget & HTMLDivElement }, + category: string | null + ) => { + event.preventDefault(); + + if (draggedCategory !== category && preferences && draggedCategory) { + draggedOverCategory = category; + + const categories = preferences.pinned_badge_wall_categories; + const draggedIndex = categories.indexOf(draggedCategory); + const targetIndex = categories.indexOf(category || ''); + + categories.splice(draggedIndex, 1); + categories.splice(targetIndex, 0, draggedCategory); + + preferences.pinned_badge_wall_categories = categories; + } + }; + + const handleDragLeave = ( + event: DragEvent & { currentTarget: EventTarget & HTMLDivElement }, + category: string + ) => { + event.preventDefault(); + + if (draggedOverCategory === category && preferences && draggedCategory) { + draggedOverCategory = null; + + const categories = preferences.pinned_badge_wall_categories; + const draggedIndex = categories.indexOf(draggedCategory); + + categories.splice(draggedIndex, 1); + categories.splice(categories.indexOf(category) + 1, 0, draggedCategory); + + preferences.pinned_badge_wall_categories = categories; + } + }; + + const handleDrop = (event: { preventDefault: () => void }) => { + event.preventDefault(); + + if (userData && preferences) + setCategoriesQuery + .mutate({ + categories: preferences.pinned_badge_wall_categories + }) + .then(); + + draggedCategory = null; + draggedOverCategory = null; + }; + + onMount(async () => { + schedule = typeSchedule( + parseScheduleHtml( + await ( + await fetch(proxy('https://schedule.hololive.tv'), { + headers: { + Cookie: 'timezone=Asia/Tokyo' + } + }) + ).text() + ) + ); + }); + + const getBadgeWallCSS = () => + (document.getElementById('badgeWallCSS') as HTMLTextAreaElement).value; + + const getBiography = () => + (document.getElementById('biography') as HTMLTextAreaElement).value.slice(0, 3000); + + const toggleCategory = () => { + if (!userData) return; + + const categoryElement = document.getElementById('category') as HTMLInputElement; + const category = categoryElement.value; + + toggleCategoryQuery.mutate({ category }).then(); + + categoryElement.value = ''; + }; - // 8.5827814569536423841e0 + // 8.5827814569536423841e0 </script> <HeadTitle route={`${data.username}'s Profile`} path={`/user/${data.username}`} /> {#if error} - <AnimeRateLimited> - <a href={`https://anilist.co/user/${data.username}`} target="_blank">@{data.username}</a>'s - profile could not be loaded. - </AnimeRateLimited> + <AnimeRateLimited> + <a href={`https://anilist.co/user/${data.username}`} target="_blank">@{data.username}</a>'s + profile could not be loaded. + </AnimeRateLimited> {:else} - {#if userData === null} - <Message slot withReload> - <p> - Could not load user profile for <a - href={`https://anilist.co/user/${data.username}`} - target="_blank">@{data.username}</a - >. - </p> - </Message> - {:else if userData === undefined} - <Skeleton card={false} bigCard count={1} height="224px" /> - - <Message message="Loading user profile ..." /> - {:else} - <div class="card card-small"> - <div - class="card user-grid" - style={`background-image: ${ - userData ? `url(${userData.bannerImage})` : 'none' - }; padding: 0;`} - > - {#if userData} - <img src={userData.bannerImage} alt="" class="cover-image" /> - {/if} - - <div class="card user-grid-content"> - <div class="user-grid-avatar"> - <LinkedTooltip content={`${userData.name}`} id="avatar" pin="avatar" relative> - <a href={`https://anilist.co/user/${userData.name}`} target="_blank"> - <ParallaxImage - source={$settings.displayDataSaver - ? userData.avatar.medium - : userData.avatar.large} - alternativeText="" - style="border-radius: 8px; width: 6.5em;" - /> - </a> - </LinkedTooltip> - </div> - - <div class="user-grid-rest"> - <p> - <a - href={`https://anilist.co/user/${userData.name}`} - target="_blank" - title={String(userData.id)} - use:tooltip - > - @{userData.name} - </a> - {#if userData && authorisedUsers.includes(userData.id)} - ‌ - <button class="unclickable-button button-badge badge-rainbow">Owner</button> - {/if} - <span class="click-item separator opaque">•</span> - <a href={root(`/user/${userData.name}/badges`)}>Badge Wall</a> - </p> - - {#if preferences && preferences.biography && preferences.biography.length > 0} - <SvelteMarkdown - source={preferences.biography} - renderers={{ - link: MarkdownLink - }} - /> - {/if} - - {$locale({ - values: { - username: userData.name, - anime: (userData.statistics.anime.minutesWatched / 60 / 24).toFixed(1), - manga: estimatedDayReading(userData.statistics.manga.chaptersRead).toFixed(1) - } - }).user.profile.statistics} - - {#if schedule && preferences && preferences.biography && preferences.biography.length > 0} - <br /> - {:else} - <p /> - {/if} - - {#if $Profile.fetching} - {displayBadges(userData.name, '...')} - {:else if $Profile.data && $Profile.data.User} - {@const badges = $Profile.data.User.badgesCount} - - {#if badges} - {displayBadges(userData.name, badges)} - {:else} - {displayBadges(userData.name, '?')} - {/if} - {:else} - {displayBadges(userData.name, '?')} - {/if} - </div> - </div> - </div> - </div> - {/if} - - {#if schedule && preferences && preferences.pinned_hololive_streams.length > 0} - <p /> - - <div class="card"> - <div class="hololive-badges"> - {#each preferences.pinned_hololive_streams as stream, index} - {@const avatar = schedule.dict[stream]} - - {#if avatar} - <LinkedTooltip - content={stream} - id={`hololive-badge-${index}`} - pin={`hololive-badge-${index}`} - relative - > - <a href={root(`/hololive/${encodeURIComponent(stream)}`)}> - <div class="user-grid-hololive-badges"> - <ParallaxImage source={avatar} alternativeText="Avatar" /> - </div> - </a> - </LinkedTooltip> - {/if} - {/each} - </div> - </div> - {/if} - - {#if preferences && userData && userData.id === $identity.id} - <p /> - - <details open> - <summary>{$locale().user.preferences.title}</summary> - - <input - type="checkbox" - on:change={() => { - if (userData) toggleHideMissingBadgesQuery.mutate(null).then(); - }} - checked={preferences.hide_missing_badges} - /> - {$locale().user.preferences.hideMissingBadges.title} - <SettingHint lineBreak>{$locale().user.preferences.hideMissingBadges.hint}</SettingHint> - - <p /> - - <input - type="checkbox" - on:change={() => { - if (userData) toggleHideAWCBadgesQuery.mutate(null).then(); - }} - checked={preferences.hide_awc_badges} - /> - {$locale().user.preferences.hideAWCBadges.title} - - <p /> - - Pinned Categories - - <div class="pinned-categories"> - {#each preferences.pinned_badge_wall_categories as category} - <div - class="card card-small pinned-category" - draggable="true" - on:dragstart={(event) => handleDragStart(event, category)} - on:dragover={handleDragOver} - on:dragenter={(event) => handleDragEnter(event, category)} - on:dragleave={(event) => handleDragLeave(event, category)} - on:drop={handleDrop} - role="button" - tabindex="0" - > - <span class="pinned-category-name"> - {category} - </span> - - <button - on:click={() => { - if (userData) toggleCategoryQuery.mutate({ category }).then(); - }}>Remove</button - > - </div> - {/each} - - <span class="card card-small pinned-category"> - <span class="pinned-category-name"> - <input type="text" id="category" placeholder="Category" style="width: 10em;" /> - </span> - - <button class="button-lined" on:click={toggleCategory}>Add</button> - </span> - </div> - - <p /> - - Biography - - <button - on:click={() => { - if (userData) - setBiographyQuery - .mutate({ - biography: getBiography() - }) - .then(); - }}>Save</button - > - <textarea - value={preferences.biography} - rows="5" - cols="100" - id="biography" - placeholder="Markdown supported!" - /> - - <p /> - - Badge Wall Custom CSS - - <button - on:click={() => { - if (userData) - setBadgeWallCSSQuery - .mutate({ - css: getBadgeWallCSS() - }) - .then(); - }}>Save</button - > - <textarea - value={preferences.badge_wall_css} - rows="10" - cols="100" - id="badgeWallCSS" - placeholder="/* Use classes and IDs such as .badges, #badges, .badge, or standard elements like body and details, or anything, as long as it's valid CSS! */" - /> - </details> - {/if} + {#if userData === null} + <Message slot withReload> + <p> + Could not load user profile for <a + href={`https://anilist.co/user/${data.username}`} + target="_blank">@{data.username}</a + >. + </p> + </Message> + {:else if userData === undefined} + <Skeleton card={false} bigCard count={1} height="224px" /> + + <Message message="Loading user profile ..." /> + {:else} + <div class="card card-small"> + <div + class="card user-grid" + style={`background-image: ${ + userData ? `url(${userData.bannerImage})` : 'none' + }; padding: 0;`} + > + {#if userData} + <img src={userData.bannerImage} alt="" class="cover-image" /> + {/if} + + <div class="card user-grid-content"> + <div class="user-grid-avatar"> + <LinkedTooltip content={`${userData.name}`} id="avatar" pin="avatar" relative> + <a href={`https://anilist.co/user/${userData.name}`} target="_blank"> + <ParallaxImage + source={$settings.displayDataSaver + ? userData.avatar.medium + : userData.avatar.large} + alternativeText="" + style="border-radius: 8px; width: 6.5em;" + /> + </a> + </LinkedTooltip> + </div> + + <div class="user-grid-rest"> + <p> + <a + href={`https://anilist.co/user/${userData.name}`} + target="_blank" + title={String(userData.id)} + use:tooltip + > + @{userData.name} + </a> + {#if userData && authorisedUsers.includes(userData.id)} + ‌ + <button class="unclickable-button button-badge badge-rainbow">Owner</button> + {/if} + <span class="click-item separator opaque">•</span> + <a href={root(`/user/${userData.name}/badges`)}>Badge Wall</a> + </p> + + {#if preferences && preferences.biography && preferences.biography.length > 0} + <SvelteMarkdown + source={preferences.biography} + renderers={{ + link: MarkdownLink + }} + /> + {/if} + + {$locale({ + values: { + username: userData.name, + anime: (userData.statistics.anime.minutesWatched / 60 / 24).toFixed(1), + manga: estimatedDayReading(userData.statistics.manga.chaptersRead).toFixed(1) + } + }).user.profile.statistics} + + {#if schedule && preferences && preferences.biography && preferences.biography.length > 0} + <br /> + {:else} + <p /> + {/if} + + {#if $Profile.fetching} + {displayBadges(userData.name, '...')} + {:else if $Profile.data && $Profile.data.User} + {@const badges = $Profile.data.User.badgesCount} + + {#if badges} + {displayBadges(userData.name, badges)} + {:else} + {displayBadges(userData.name, '?')} + {/if} + {:else} + {displayBadges(userData.name, '?')} + {/if} + </div> + </div> + </div> + </div> + {/if} + + {#if schedule && preferences && preferences.pinned_hololive_streams.length > 0} + <p /> + + <div class="card"> + <div class="hololive-badges"> + {#each preferences.pinned_hololive_streams as stream, index} + {@const avatar = schedule.dict[stream]} + + {#if avatar} + <LinkedTooltip + content={stream} + id={`hololive-badge-${index}`} + pin={`hololive-badge-${index}`} + relative + > + <a href={root(`/hololive/${encodeURIComponent(stream)}`)}> + <div class="user-grid-hololive-badges"> + <ParallaxImage source={avatar} alternativeText="Avatar" /> + </div> + </a> + </LinkedTooltip> + {/if} + {/each} + </div> + </div> + {/if} + + {#if preferences && userData && userData.id === $identity.id} + <p /> + + <details open> + <summary>{$locale().user.preferences.title}</summary> + + <input + type="checkbox" + on:change={() => { + if (userData) toggleHideMissingBadgesQuery.mutate(null).then(); + }} + checked={preferences.hide_missing_badges} + /> + {$locale().user.preferences.hideMissingBadges.title} + <SettingHint lineBreak>{$locale().user.preferences.hideMissingBadges.hint}</SettingHint> + + <p /> + + <input + type="checkbox" + on:change={() => { + if (userData) toggleHideAWCBadgesQuery.mutate(null).then(); + }} + checked={preferences.hide_awc_badges} + /> + {$locale().user.preferences.hideAWCBadges.title} + + <p /> + + Pinned Categories + + <div class="pinned-categories"> + {#each preferences.pinned_badge_wall_categories as category} + <div + class="card card-small pinned-category" + draggable="true" + on:dragstart={(event) => handleDragStart(event, category)} + on:dragover={handleDragOver} + on:dragenter={(event) => handleDragEnter(event, category)} + on:dragleave={(event) => handleDragLeave(event, category)} + on:drop={handleDrop} + role="button" + tabindex="0" + > + <span class="pinned-category-name"> + {category} + </span> + + <button + on:click={() => { + if (userData) toggleCategoryQuery.mutate({ category }).then(); + }}>Remove</button + > + </div> + {/each} + + <span class="card card-small pinned-category"> + <span class="pinned-category-name"> + <input type="text" id="category" placeholder="Category" style="width: 10em;" /> + </span> + + <button class="button-lined" on:click={toggleCategory}>Add</button> + </span> + </div> + + <p /> + + Biography + + <button + on:click={() => { + if (userData) + setBiographyQuery + .mutate({ + biography: getBiography() + }) + .then(); + }}>Save</button + > + <textarea + value={preferences.biography} + rows="5" + cols="100" + id="biography" + placeholder="Markdown supported!" + /> + + <p /> + + Badge Wall Custom CSS + + <button + on:click={() => { + if (userData) + setBadgeWallCSSQuery + .mutate({ + css: getBadgeWallCSS() + }) + .then(); + }}>Save</button + > + <textarea + value={preferences.badge_wall_css} + rows="10" + cols="100" + id="badgeWallCSS" + placeholder="/* Use classes and IDs such as .badges, #badges, .badge, or standard elements like body and details, or anything, as long as it's valid CSS! */" + /> + </details> + {/if} {/if} <style lang="scss"> - .user-grid-content { - display: flex; - flex-wrap: wrap; - column-gap: 1.5em; - background-color: rgba(0, 0, 0, 0.468); - color: #d8d8d8; - border-top-left-radius: 0; - border-top-right-radius: 0; - } - - .user-grid-avatar { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - } - - .click-item { - margin: 0 0.625rem; - } - - .user-grid { - background-size: cover; - background-position: center; - background-repeat: no-repeat; - } - - .cover-image { - visibility: hidden; - height: 4.5em; - } - - .user-grid-hololive-badges { - $transitionDuration: 0.45s; - $transition: transform $transitionDuration ease, box-shadow $transitionDuration ease; - $size: 5.25em; - - border-radius: 8px; - width: $size; - height: $size; - object-fit: cover; - transition: $transition; - box-shadow: rgba(0, 0, 11, 0.1) 0px 7px 29px 0px; - overflow: hidden; - - &:hover { - z-index: 2; - transition: $transition; - transform: scale(1.15); - box-shadow: 0 1.5px 9px var(--base01), 0 0 0 4px var(--base02), 0 4px 30px var(--base01); - } - } - - .hololive-badges { - display: flex; - gap: 1rem; - border-radius: 8px; - justify-content: space-around; - flex-wrap: wrap; - } - - .separator { - color: var(--base04); - } - - .user-grid-rest { - flex: 1; - } - - .pinned-categories { - display: flex; - flex-wrap: wrap; - gap: 1rem; - } - - .pinned-category { - display: flex; - align-items: center; - } - - .pinned-category-name { - margin-right: 0.5em; - } + .user-grid-content { + display: flex; + flex-wrap: wrap; + column-gap: 1.5em; + background-color: rgba(0, 0, 0, 0.468); + color: #d8d8d8; + border-top-left-radius: 0; + border-top-right-radius: 0; + } + + .user-grid-avatar { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + } + + .click-item { + margin: 0 0.625rem; + } + + .user-grid { + background-size: cover; + background-position: center; + background-repeat: no-repeat; + } + + .cover-image { + visibility: hidden; + height: 4.5em; + } + + .user-grid-hololive-badges { + $transitionDuration: 0.45s; + $transition: transform $transitionDuration ease, box-shadow $transitionDuration ease; + $size: 5.25em; + + border-radius: 8px; + width: $size; + height: $size; + object-fit: cover; + transition: $transition; + box-shadow: rgba(0, 0, 11, 0.1) 0px 7px 29px 0px; + overflow: hidden; + + &:hover { + z-index: 2; + transition: $transition; + transform: scale(1.15); + box-shadow: 0 1.5px 9px var(--base01), 0 0 0 4px var(--base02), 0 4px 30px var(--base01); + } + } + + .hololive-badges { + display: flex; + gap: 1rem; + border-radius: 8px; + justify-content: space-around; + flex-wrap: wrap; + } + + .separator { + color: var(--base04); + } + + .user-grid-rest { + flex: 1; + } + + .pinned-categories { + display: flex; + flex-wrap: wrap; + gap: 1rem; + } + + .pinned-category { + display: flex; + align-items: center; + } + + .pinned-category-name { + margin-right: 0.5em; + } </style> |